Ruby 日記 44日目: 配列とその要素の凍結
次のプログラムを実行するとどうなりますか
code:gold/ex44/main.rb
array.each do |chr|
chr.upcase!
end
p array
選択肢:
例外が発生する
["a", "b", "c"]と表示される
["A", "B", "C"]と表示される
["d", "e", "f"]と表示される
解説:
類似問題は
だね
オブジェクトを凍結(内容の変更を禁止)します。
凍結されたオブジェクトの変更は 例外 RuntimeError を発生させます。 いったん凍結されたオブジェクトを元に戻す方法はありません。
凍結されるのはオブジェクトであり、変数ではありません。代入などで変数の指す オブジェクトが変化してしまうことは freeze では防げません。 freeze が防ぐのは、 `破壊的な操作' と呼ばれるもの一般です。
今回の問題では "a", "b", "c" のそれぞれに対して破壊的な変更 String#upcase! がされている。
「凍結された配列に対して、その要素についても破壊的な変更が禁止されるのか?」が今回の問題の肝だね。
公式リファレンスの記載を発見できていないのだけど、
配列の凍結において
「配列の破壊的な変更を禁止されるが、配列の要素の破壊的な変更は禁止されない」というのがRubyの仕様なのだよな。
なので正解は「["A", "B", "C"]と表示される」だね〜。
code:sh
# ruby gold/ex44/main.rb
/icons/hr.icon
配列の要素も凍結したいのであれば、こう書くと良い
code:gold/ex44/sample.rb
array.each do |chr|
chr.upcase!
end
p array
code:sh
# ruby gold/ex44/sample.rb
gold/ex44/sample.rb:4:in `upcase!': can't modify frozen String (RuntimeError)
from gold/ex44/sample.rb:4:in `block in <main>'
from gold/ex44/sample.rb:3:in `each'
from gold/ex44/sample.rb:3:in `<main>'